#include "app_buffer.h"

// 初始化Base_buffer_t结构体，并返回指向该结构体的指针
static Base_buffer_t *Base_buffer_init(int buffer_size)
{
    // 分配Base_buffer_t结构体大小的内存空间
    Base_buffer_t *base_buffer = malloc(sizeof(Base_buffer_t));
    // 将buffer_len初始化为0
    base_buffer->buffer_len = 0;
    // 分配buffer_size大小的内存空间
    base_buffer->buffer = malloc(buffer_size);
    base_buffer->buffer_size = buffer_size;
    // 返回指向Base_buffer_t结构体的指针
    return base_buffer;
}

static void buffer_switch(Double_buffer_t *double_buffer)
{
    // 加锁(等待写操作完成)
    pthread_mutex_lock(&double_buffer->write_mutex);
    int temp = double_buffer->read_index;
    // 交换读写索引
    double_buffer->read_index = double_buffer->write_index;
    // 更新写索引
    double_buffer->write_index = temp;
    // 解锁
    pthread_mutex_unlock(&double_buffer->write_mutex);
}

Double_buffer_t *app_buffer_init(int buffer_size)
{
    // 分配Double_buffer_t结构体大小的内存空间
    Double_buffer_t *double_buffer = malloc(sizeof(Double_buffer_t));

    // 如果分配失败
    if (double_buffer == NULL)
    {
        // 记录错误日志
        log_error("malloc double_buffer failed");
        // 返回-1
        return NULL;
    }

    // 初始化缓冲区
    double_buffer->buffers[0] = Base_buffer_init(buffer_size);
    double_buffer->buffers[1] = Base_buffer_init(buffer_size);

    // 初始化读写索引
    double_buffer->read_index = 0;
    double_buffer->write_index = 1;

    // 初始化读写互斥锁
    pthread_mutex_init(&double_buffer->read_mutex, NULL);
    pthread_mutex_init(&double_buffer->write_mutex, NULL);

    return double_buffer;
}

int app_buffer_write(Double_buffer_t *double_buffer, unsigned char *data, unsigned char data_len)
{
    if (double_buffer == NULL || data == NULL || data_len == 0)
    {
        log_error("double_buffer or data is NULL or data_len is 0");
        return -1;
    }
    // 加写锁
    pthread_mutex_lock(&double_buffer->write_mutex);

    // 获取写缓冲区地址
    Base_buffer_t *write_buffer = double_buffer->buffers[double_buffer->write_index];
    // 如果缓冲区已满,或容纳不下新的数据
    if (write_buffer->buffer_len + data_len + 1 > write_buffer->buffer_size)
    {
        log_error("buffer is full or data_len is too long");
        // 解写锁
        pthread_mutex_unlock(&double_buffer->write_mutex);
        return -1;
    }

    // 将数据写入缓冲区
    write_buffer->buffer[write_buffer->buffer_len] = data_len;                   // 先将数据长度写入缓冲区
    memcpy(write_buffer->buffer + write_buffer->buffer_len + 1, data, data_len); // 写入具体的数据
    // 更新缓冲区长度
    write_buffer->buffer_len += data_len + 1;

    // 解写锁
    pthread_mutex_unlock(&double_buffer->write_mutex);
    return 0;
}

int app_buffer_read(Double_buffer_t *double_buffer, unsigned char *data, unsigned char data_size)
{
    if (double_buffer == NULL || data == NULL || data_size == 0)
    {
        log_error("double_buffer or data is NULL or data_size is 0");
        return -1;
    }
    // 加读锁
    pthread_mutex_lock(&double_buffer->read_mutex);

    // 获取读缓冲区地址
    Base_buffer_t *read_buffer = double_buffer->buffers[double_buffer->read_index];

    if (read_buffer == NULL)
    {
        log_error("read_buffer is NULL");
        // 解读锁
        pthread_mutex_unlock(&double_buffer->read_mutex);
        return -1;
    }

    // 如果缓冲区为空
    if (read_buffer->buffer_len == 0)
    {
        // 切换到另一个缓冲区
        buffer_switch(double_buffer);

        // 重新获取读缓冲区地址
        read_buffer = double_buffer->buffers[double_buffer->read_index];

        // 如果切换后缓冲区仍然为空,则返回0
        if (read_buffer->buffer_len == 0)
        {
            // 解读锁
            pthread_mutex_unlock(&double_buffer->read_mutex);
            return 0;
        }
    }
    // 读取数据
    if (read_buffer->buffer[0] > data_size)
    {
        log_error("data_size is too small");
        // 解读锁
        pthread_mutex_unlock(&double_buffer->read_mutex);
        return -1;
    }
    // 获取读到的数据长度
    int data_len = read_buffer->buffer[0];
    // 将数据拷贝到data中
    memcpy(data, read_buffer->buffer + 1, data_len);
    // 将未读的数据移动到前面
    memmove(read_buffer->buffer, read_buffer->buffer + data_len + 1, read_buffer->buffer_len - data_len - 1);
    // 更新缓冲区长度
    read_buffer->buffer_len -= (data_len + 1);

    // 解读锁
    pthread_mutex_unlock(&double_buffer->read_mutex);

    return data_len;
}

void app_buffer_free(Double_buffer_t *double_buffer)
{
    // 释放缓冲区内存
    free(double_buffer->buffers[0]->buffer);
    free(double_buffer->buffers[1]->buffer);
    free(double_buffer->buffers[0]);
    free(double_buffer->buffers[1]);
    // 释放读写互斥锁
    pthread_mutex_destroy(&double_buffer->read_mutex);
    pthread_mutex_destroy(&double_buffer->write_mutex);
    // 释放双缓冲内存
    free(double_buffer);
}